Singleton, the PHP way
You can also be interested in:
I realized that even if the great part of my work consists in programming PHP stuff, I rarely write about PHP in my posts, maybe because I really don't like it?
But today I'll write about a way to implement the singleton pattern with PHP.
This is quite an easy job making use of PHP 5.3.0, thanks to the "Late Static Binding" feature. In particular we'll use the get_called_class
method and the static
keyword. Notice that static in PHP 5.3's late static bindings refers to whatever class in the hierarchy which you call the method on, so its behavior is quite different from the keyword self. That is, if I call a class method which is inherited from a parent class, inside that class the static keyword refers to the children while the self keyword refers to the parent, got it?
The singleton pattern is used when we want to be sure that only one instance of a class exists, and this instance is shared between all classes. In other words, every time an instance of such class is required, then the unique instance is returned.
Probably the most frequent use case of the singleton pattern when dealing with the development of web applications is the database manager class. Implementing the db class manager as a singleton assures the existence of only one instance, only one active connection to the database etc...
I also use the singleton pattern for the implementation of a sort of register. An object which stores data that should be available to all other objects and in every part of the software.
Now let's see the code.
<?php
/**
* @file singleton.class.php
* @brief Contains the singleton class.
*
* @author abidibo abidibo@gmail.com
* @version 0.1
* @copyright abidibo [MIT License](http://www.opensource.org/licenses/mit-license.php)
*/
/**
* @brief Singleton primitive class
* @description Class which implemets the singleton pattern and assures the existence of only one object instance
*
* @author abidibo abidibo@gmail.com
* @version 0.1
* @copyright abidibo [MIT License](http://www.opensource.org/licenses/mit-license.php)
*/
abstract class singleton {
/*
* @brief array containing the singleton instances
*/
protected static $_instances = array();
/**
* @brief Singleton constructor
*
* This method is protected in order to deny direct object instantiation outside this class and the ones
* which extends it
*
* @return void
*/
protected function __construct() {
}
/**
* @brief Method used to retrieve singleton instances
*
* if the singleton instance already exists returns it, otherwise creates an instance and returns it
*
* @return mixed the singleton instance
*/
public static function instance() {
$class = get_called_class();
if(array_key_exists($class, self::$_instances) === false) {
self::$_instances[$class] = new static();
}
return self::$_instances[$class];
}
/**
* @brief Clone method
*
* Singleton cloning is denied
*
* @return error
*/
public function __clone() {
$error = 'singleton can\'t be cloned';
throw new Exception($error);
}
/**
* @brief Sleep method
*
* Singleton serialization is denied
*
* @return error
*/
public function __sleep() {
$error = 'singleton can\'t be serialized';
throw new Exception($error);
}
/**
* @brief Wakeup method
*
* Singleton serialization is denied
*
* @return error
*/
public function __wakeup() {
$error = 'singleton can\'t be serialized';
throw new Exception($error);
}
}
The __constructor
method is protected so that it is impossible to instantiate directly a singleton class. Who want a singleton instance must call the static instance
method, which includes "all the magic".
Clearly also the magic methods used to clone and serialize an object are "forbidden".
That's all, as usual comments are welcome, maybe there are several better ways to implement the singleton pattern, if so let me know!
Your Smartwatch Loves Tasker!
Your Smartwatch Loves Tasker!
Featured
Archive
- 2021
- 2020
- 2019
- 2018
- 2017
- Nov
- Oct
- Aug
- Jun
- Mar
- Feb
- 2016
- Oct
- Jun
- May
- Apr
- Mar
- Feb
- Jan
- 2015
- Nov
- Oct
- Aug
- Apr
- Mar
- Feb
- Jan
- 2014
- Sep
- Jul
- May
- Apr
- Mar
- Feb
- Jan
- 2013
- Nov
- Oct
- Sep
- Aug
- Jul
- Jun
- May
- Apr
- Mar
- Feb
- Jan
- 2012
- Dec
- Nov
- Oct
- Aug
- Jul
- Jun
- May
- Apr
- Jan
- 2011
- Dec
- Nov
- Oct
- Sep
- Aug
- Jul
- Jun
- May